package org.gdstash.db;

import org.gdstash.description.BonusDetail;
import org.gdstash.description.TagInfo;
import org.gdstash.description.TagInfoHashMap;
import org.gdstash.util.GDMsgFormatter;
import org.gdstash.util.GDMsgLogger;

import java.sql.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class DBStat implements Cloneable, Comparable<DBStat> {
    public static final String TABLE_NAME_ITEM = "GD_ITEM_STAT";
    public static final String TABLE_NAME_ITEMSET = "GD_ITEMSET_STAT";
    public static final String TABLE_NAME_AFFIX = "GD_AFFIX_STAT";
    public static final String TABLE_NAME_SKILL = "GD_SKILL_STAT";
    public static final String FIELD_ID_ITEM = "ITEM_ID";
    public static final String FIELD_ID_ITEMSET = "ITEMSET_ID";
    private static final String FIELD_ID_AFFIX = "AFFIX_ID";
    private static final String FIELD_ID_SKILL = "SKILL_ID";
    private static final int ROW_ITEM_ID = 1;
    private static final int ROW_STAT_TYPE = 2;
    private static final int ROW_SKILL_LEVEL = 3;
    private static final int ROW_FLAG_GLOBAL = 4;
    private static final int ROW_FLAG_XOR = 5;
    private static final int ROW_STAT_MIN = 6;
    private static final int ROW_STAT_MAX = 7;
    private static final int ROW_STAT_CHANCE = 8;
    private static final int ROW_MODIFIER = 9;
    private static final int ROW_MODIFIER_CHANCE = 10;
    private static final int ROW_DURATION_MIN = 11;
    private static final int ROW_DURATION_MAX = 12;
    private static final int ROW_DURATION_CHANCE = 13;
    private static final int ROW_DURATION_MODIFIER = 14;
    private static final int ROW_DURATION_MODIFIER_CHANCE = 15;
    private static final int ROW_MAX_RESIST = 16;
    public static final int GLOBAL_NONE = 0;
    public static final int GLOBAL_ITEM = 1;
    public static final int GLOBAL_COMPONENT = 2;
    public static final int GLOBAL_PREFIX = 3;
    public static final int GLOBAL_PREFIX_PET = 4;
    public static final int GLOBAL_SUFFIX = 5;
    public static final int GLOBAL_SUFFIX_PET = 6;
    public static final int GLOBAL_MODIFIER = 7;
    public static final int GLOBAL_COMPLETION = 8;
    public static final int GLOBAL_ENCHANTMENT = 9;
    public static final String TYPE_SKILL_TRIGGER_HEALTH_PCT = "lifeMonitorPercent";
    public static final String TYPE_SKILL_PET_SUMMON_INC = "petBurstSpawn";
    public static final String TYPE_SKILL_PET_LIMIT_INC = "petLimit";
    public static final String TYPE_SKILL_MAX_LEVEL_INC = "skillMaxLevel";
    public static final String TYPE_SKILL_SPARK_INC = "sparkMaxNumber";
    public static final String TYPE_SKILL_TARGET_INC = "skillTargetNumber";
    public static final String TYPE_SKILL_DURATION = "skillActiveDuration";
    public static final String TYPE_SKILL_COOLDOWN_RED_PCT = "skillCooldownReduction";
    public static final String TYPE_SKILL_RECHARGE_TIME = "skillCooldownTime";
    public static final String TYPE_SKILL_HEALTH = "skillLifeBonus";
    public static final String TYPE_SKILL_HEALTH_PCT = "skillLifePercent";
    public static final String TYPE_SKILL_MANA_COST = "skillManaCost";
    public static final String TYPE_SKILL_MANA_COST_RED_PCT = "skillManaCostReduction";
    public static final String TYPE_SKILL_TARGET_RADIUS = "skillTargetRadius";
    public static final String TYPE_SKILL_WEAPON_DAMAGE_PCT = "weaponDamagePct";
    public static final String TYPE_SKILL_DAMAGE_ABSORB_PCT = "damageAbsorptionPercent";
    public static final String TYPE_SHIELD_RECOVERY_TIME = "blockRecoveryTime";
    public static final String TYPE_CHAR_ARMOR_PHYSIQUE_RED_PCT = "characterArmorStrengthReqReduction";
    public static final String TYPE_CHAR_ATTACK_SPEED = "characterAttackSpeed";
    public static final String TYPE_CHAR_CONSTITUTION = "characterConstitution";
    public static final String TYPE_CHAR_DEFENSIVE_ABILITY = "characterDefensiveAbility";
    public static final String TYPE_CHAR_SHIELD_REC_RED_PCT = "characterDefensiveBlockRecoveryReduction";
    public static final String TYPE_CHAR_AVOID_PROJECTILE_PCT = "characterDeflectProjectile";
    public static final String TYPE_CHAR_CUNNING = "characterDexterity";
    public static final String TYPE_CHAR_AVOID_MELEE_PCT = "characterDodgePercent";
    public static final String TYPE_CHAR_ENERGY_ABSORB_PCT = "characterEnergyAbsorptionPercent";
    public static final String TYPE_CHAR_REQUIREMENT_RED_PCT = "characterGlobalReqReduction";
    public static final String TYPE_CHAR_HEAL_INC_PCT = "characterHealIncreasePercent";
    public static final String TYPE_CHAR_RANGED_CUNNING_RED_PCT = "characterHuntingDexterityReqReduction";
    public static final String TYPE_CHAR_INC_EXPERIENCE_PCT = "characterIncreasedExperience";
    public static final String TYPE_CHAR_SPIRIT = "characterIntelligence";
    public static final String TYPE_CHAR_JEWELRY_SPIRIT_RED_PCT = "characterJewelryIntelligenceReqReduction";
    public static final String TYPE_CHAR_HEALTH = "characterLife";
    public static final String TYPE_CHAR_HEALTH_REGEN = "characterLifeRegen";
    public static final String TYPE_CHAR_LIGHT_RADIUS_PCT = "characterLightRadius";
    public static final String TYPE_CHAR_MANA = "characterMana";
    public static final String TYPE_CHAR_MANA_LIMIT = "characterManaLimitReserve";
    public static final String TYPE_CHAR_MANA_RESERVE = "characterManaLimitReserveReduction";
    public static final String TYPE_CHAR_MANA_REGEN = "characterManaRegen";
    public static final String TYPE_CHAR_MELEE_CUNNING_RED_PCT = "characterMeleeDexterityReqReduction";
    public static final String TYPE_CHAR_MELEE_PHYSIQUE_RED_PCT = "characterMeleeStrengthReqReduction";
    public static final String TYPE_CHAR_OFFENSIVE_ABILITY = "characterOffensiveAbility";
    public static final String TYPE_CHAR_RUN_SPEED = "characterRunSpeed";
    public static final String TYPE_CHAR_SHIELD_STRENGTH_RED_PCT = "characterShieldStrengthReqReduction";
    public static final String TYPE_CHAR_CAST_SPEED = "characterSpellCastSpeed";
    public static final String TYPE_CHAR_PHYSIQUE = "characterStrength";
    public static final String TYPE_CHAR_TOTAL_SPEED = "characterTotalSpeed";
    public static final String TYPE_CHAR_WEAPON_SPIRIT_RED_PCT = "characterWeaponIntelligenceReqReduction";
    public static final String TYPE_CHAR_WEAPON_PHYSIQUE_RED_PCT = "characterWeaponStrengthReqReduction";
    public static final String TYPE_CHAR_WEAPON_2H_PHYS_RED_PCT = "characterWeapon2HStrengthReqReduction";
    public static final String TYPE_CHAR_CONVERSION_PCT = "conversionPercentage";
    public static final String TYPE_CHAR_CONVERSION_PCT_2 = "conversionPercentage2";
    public static final String TYPE_CHAR_RACE_DAMAGE_PCT = "racialBonusPercentDamage";
    public static final String TYPE_WEAPON_PROJECTILE_PIERCE = "piercingProjectile";
    public static final String TYPE_CHAR_LEVEL_REQ_RED = "characterLevelReqReduction";
    public static final String TYPE_DEF_ABSORTPION = "defensiveAbsorption";
    public static final String TYPE_DEF_AETHER = "defensiveAether";
    public static final String TYPE_DEF_ALL = "defensiveAll";
    public static final String TYPE_DEF_BLEED = "defensiveBleeding";
    public static final String TYPE_DEF_BLOCK_CHANCE = "defensiveBlock";
    public static final String TYPE_DEF_BLOCK_AMOUNT = "defensiveBlockAmount";
    public static final String TYPE_DEF_BONUS_PROTECT = "defensiveBonusProtection";
    public static final String TYPE_DEF_CHAOS = "defensiveChaos";
    public static final String TYPE_DEF_COLD = "defensiveCold";
    public static final String TYPE_DEF_CONFUSION = "defensiveConfusion";
    public static final String TYPE_DEF_CONVERT = "defensiveConvert";
    public static final String TYPE_DEF_DISRUPTION = "defensiveDisruption";
    public static final String TYPE_DEF_ELEMENTAL = "defensiveElemental";
    public static final String TYPE_DEF_ELEMENTAL_RES = "defensiveElementalResistance";
    public static final String TYPE_DEF_FEAR = "defensiveFear";
    public static final String TYPE_DEF_FIRE = "defensiveFire";
    public static final String TYPE_DEF_FREEZE = "defensiveFreeze";
    public static final String TYPE_DEF_KNOCKDOWN = "defensiveKnockdown";
    public static final String TYPE_DEF_LIFE = "defensiveLife";
    public static final String TYPE_DEF_LIGHTNING = "defensiveLightning";
    public static final String TYPE_DEF_LIFE_PERC = "defensivePercentCurrentLife";
    public static final String TYPE_DEF_REFLECT_PERC = "defensivePercentReflectionResistance";
    public static final String TYPE_DEF_MANA_BURN = "defensiveManaBurnRatio";
    public static final String TYPE_DEF_PETRIFY = "defensivePetrify";
    public static final String TYPE_DEF_PHYSICAL = "defensivePhysical";
    public static final String TYPE_DEF_PIERCE = "defensivePierce";
    public static final String TYPE_DEF_POISON = "defensivePoison";
    public static final String TYPE_DEF_PROTECTION = "defensiveProtection";
    public static final String TYPE_DEF_REFLECT = "defensiveReflect";
    public static final String TYPE_DEF_SLEEP = "defensiveSleep";
    public static final String TYPE_DEF_SLOW_LIFE_LEECH = "defensiveSlowLifeLeach";
    public static final String TYPE_DEF_SLOW_MANA_LEECH = "defensiveSlowManaLeach";
    public static final String TYPE_DEF_STUN = "defensiveStun";
    public static final String TYPE_DEF_TAUNT = "defensiveTaunt";
    public static final String TYPE_DEF_TOTALSPEED_RES = "defensiveTotalSpeedResistance";
    public static final String TYPE_DEF_TRAP = "defensiveTrap";
    public static final String TYPE_OFF_AETHER = "offensiveAether";
    public static final String TYPE_OFF_BASE_AETHER = "offensiveBaseAether";
    public static final String TYPE_OFF_BASE_CHAOS = "offensiveBaseChaos";
    public static final String TYPE_OFF_BASE_COLD = "offensiveBaseCold";
    public static final String TYPE_OFF_BASE_FIRE = "offensiveBaseFire";
    public static final String TYPE_OFF_BASE_LIFE = "offensiveBaseLife";
    public static final String TYPE_OFF_BASE_LIGHTNING = "offensiveBaseLightning";
    public static final String TYPE_OFF_BASE_POISON = "offensiveBasePoison";
    public static final String TYPE_OFF_BONUS_PHYSICAL = "offensiveBonusPhysical";
    public static final String TYPE_OFF_CHAOS = "offensiveChaos";
    public static final String TYPE_OFF_COLD = "offensiveCold";
    public static final String TYPE_OFF_CONFUSION = "offensiveConfusion";
    public static final String TYPE_OFF_CONVERT = "offensiveConvert";
    public static final String TYPE_OFF_CRITICAL = "offensiveCritDamage";
    public static final String TYPE_OFF_DMGMULT = "offensiveDamageMult";
    public static final String TYPE_OFF_DISRUPTION = "offensiveDisruption";
    public static final String TYPE_OFF_ELEMENTAL = "offensiveElemental";
    public static final String TYPE_OFF_ELEM_DMG_RED_PERC = "offensiveElementalReductionPercent";
    public static final String TYPE_OFF_ELEM_RES_RED_ABS = "offensiveElementalResistanceReductionAbsolute";
    public static final String TYPE_OFF_ELEM_RES_RED_PERC = "offensiveElementalResistanceReductionPercent";
    public static final String TYPE_OFF_FEAR = "offensiveFear";
    public static final String TYPE_OFF_FIRE = "offensiveFire";
    public static final String TYPE_OFF_FREEZE = "offensiveFreeze";
    public static final String TYPE_OFF_FUMBLE = "offensiveFumble";
    public static final String TYPE_OFF_KNOCKDOWN = "offensiveKnockdown";
    public static final String TYPE_OFF_LIFE = "offensiveLife";
    public static final String TYPE_OFF_LIFE_LEECH = "offensiveLifeLeech";
    public static final String TYPE_OFF_LIGHTNING = "offensiveLightning";
    public static final String TYPE_OFF_MANA_BURN_RATIO = "offensiveManaBurnDamageRatio";
    public static final String TYPE_OFF_MANA_BURN_DRAIN = "offensiveManaBurnDrain";
    public static final String TYPE_OFF_LIFE_PERC = "offensivePercentCurrentLife";
    public static final String TYPE_OFF_PETRIFY = "offensivePetrify";
    public static final String TYPE_OFF_PHYSICAL = "offensivePhysical";
    public static final String TYPE_OFF_PHYS_DMG_RED_PERC = "offensivePhysicalReductionPercent";
    public static final String TYPE_OFF_PHYS_RES_RED_ABS = "offensivePhysicalResistanceReductionAbsolute";
    public static final String TYPE_OFF_PHYS_RES_RED_PERC = "offensivePhysicalResistanceReductionPercent";
    public static final String TYPE_OFF_PIERCE = "offensivePierce";
    public static final String TYPE_OFF_PIERCE_RATIO = "offensivePierceRatio";
    public static final String TYPE_OFF_POISON = "offensivePoison";
    public static final String TYPE_OFF_PROJECTILE_FUMBLE = "offensiveProjectileFumble";
    public static final String TYPE_OFF_SLEEP = "offensiveSleep";
    public static final String TYPE_OFF_SLOW_ATTACK = "offensiveSlowAttackSpeed";
    public static final String TYPE_OFF_SLOW_BLEED = "offensiveSlowBleeding";
    public static final String TYPE_OFF_SLOW_COLD = "offensiveSlowCold";
    public static final String TYPE_OFF_SLOW_DEFENSE = "offensiveSlowDefensiveAbility";
    public static final String TYPE_OFF_SLOW_DEF_RED = "offensiveSlowDefensiveReduction";
    public static final String TYPE_OFF_SLOW_FIRE = "offensiveSlowFire";
    public static final String TYPE_OFF_SLOW_LIFE = "offensiveSlowLife";
    public static final String TYPE_OFF_SLOW_LIFE_LEECH = "offensiveSlowLifeLeach";
    public static final String TYPE_OFF_SLOW_LIGHTNING = "offensiveSlowLightning";
    public static final String TYPE_OFF_SLOW_MANA_LEECH = "offensiveSlowManaLeach";
    public static final String TYPE_OFF_SLOW_OFFENSE = "offensiveSlowOffensiveAbility";
    public static final String TYPE_OFF_SLOW_OFF_RED = "offensiveSlowOffensiveReduction";
    public static final String TYPE_OFF_SLOW_PHYSICAL = "offensiveSlowPhysical";
    public static final String TYPE_OFF_SLOW_POISON = "offensiveSlowPoison";
    public static final String TYPE_OFF_SLOW_RUNSPEED = "offensiveSlowRunSpeed";
    public static final String TYPE_OFF_SLOW_TOTALSPEED = "offensiveSlowTotalSpeed";
    public static final String TYPE_OFF_STUN = "offensiveStun";
    public static final String TYPE_OFF_TAUNT = "offensiveTaunt";
    public static final String TYPE_OFF_TOTALDAMAGE = "offensiveTotalDamage";
    public static final String TYPE_OFF_TOTALDMGRED_PERC = "offensiveTotalDamageReductionPercent";
    public static final String TYPE_OFF_TOTALRESRED_ABS = "offensiveTotalResistanceReductionAbsolute";
    public static final String TYPE_OFF_TOTALRESRED_PERC = "offensiveTotalResistanceReductionPercent";
    public static final String TYPE_OFF_TRAP = "offensiveTrap";
    public static final String TYPE_RET_AETHER = "retaliationAether";
    public static final String TYPE_RET_CHAOS = "retaliationChaos";
    public static final String TYPE_RET_COLD = "retaliationCold";
    public static final String TYPE_RET_CONFUSION = "retaliationConfusion";
    public static final String TYPE_RET_CONVERT = "retaliationConvert";
    public static final String TYPE_RET_DAMAGE_PCT = "retaliationDamagePct";
    public static final String TYPE_RET_ELEMENTAL = "retaliationElemental";
    public static final String TYPE_RET_FEAR = "retaliationFear";
    public static final String TYPE_RET_FIRE = "retaliationFire";
    public static final String TYPE_RET_FREEZE = "retaliationFreeze";
    public static final String TYPE_RET_LIFE = "retaliationLife";
    public static final String TYPE_RET_LIGHTNING = "retaliationLightning";
    public static final String TYPE_RET_LIFE_PERC = "retaliationPercentCurrentLife";
    public static final String TYPE_RET_PETRIFY = "retaliationPetrify";
    public static final String TYPE_RET_PHYSICAL = "retaliationPhysical";
    public static final String TYPE_RET_PIERCE = "retaliationPierce";
    public static final String TYPE_RET_PIERCE_RATIO = "retaliationPierceRatio";
    public static final String TYPE_RET_POISON = "retaliationPoison";
    public static final String TYPE_RET_SLEEP = "retaliationSleep";
    public static final String TYPE_RET_SLOW_ATTACK = "retaliationSlowAttackSpeed";
    public static final String TYPE_RET_SLOW_BLEED = "retaliationSlowBleeding";
    public static final String TYPE_RET_SLOW_COLD = "retaliationSlowCold";
    public static final String TYPE_RET_SLOW_DEFENSE = "retaliationSlowDefensiveAbility";
    public static final String TYPE_RET_SLOW_FIRE = "retaliationSlowFire";
    public static final String TYPE_RET_SLOW_LIFE = "retaliationSlowLife";
    public static final String TYPE_RET_SLOW_LIFE_LEECH = "retaliationSlowLifeLeach";
    public static final String TYPE_RET_SLOW_LIGHTNING = "retaliationSlowLightning";
    public static final String TYPE_RET_SLOW_MANA_LEECH = "retaliationSlowManaLeach";
    public static final String TYPE_RET_SLOW_OFFENSE = "retaliationSlowOffensiveAbility";
    public static final String TYPE_RET_SLOW_OFF_RED = "retaliationSlowOffensiveReduction";
    public static final String TYPE_RET_SLOW_PHYSICAL = "retaliationSlowPhysical";
    public static final String TYPE_RET_SLOW_POISON = "retaliationSlowPoison";
    public static final String TYPE_RET_SLOW_RUNSPEED = "retaliationSlowRunSpeed";
    public static final String TYPE_RET_STUN = "retaliationStun";
    public static final String TYPE_RET_TOTALDAMAGE = "retaliationTotalDamage";
    public static final String TYPE_RET_TRAP = "retaliationTrap";
    public static final String STAT_SPEED_TOTAL = "STAT_SPEED_TOTAL";
    public static final String STAT_COOLDOWN_REDUCTION = "STAT_COOLDOWN_REDUCTION";
    public static final String STAT_SKILL_RECHARGE_REDUCTION = "STAT_SKILL_RECHARGE_REDUCTION";
    public static final String STAT_BASE_ATTACKSPEED = "STAT_BASE_ATTACKSPEED";
    public static final String STAT_SPEED_ATTACK = "STAT_SPEED_ATTACK";
    public static final String STAT_SPEED_CAST = "STAT_SPEED_CAST";
    public static final String STAT_SPEED_RUN = "STAT_SPEED_RUN";
    public static final String STAT_SHIELD_RECOVERY_TIME = "STAT_SHIELD_RECOVERY_TIME";
    public static final String STAT_SHIELD_RECOVERY_RED = "STAT_SHIELD_RECOVERY_RED";
    public static final String STAT_XP_INCREASE = "STAT_XP_INCREASE";
    public static final String STAT_MANACOST_REDUCTION = "STAT_MANACOST_REDUCTION";
    public static final String STAT_REQ_REDUCTION = "STAT_REQ_REDUCTION";
    public static final String STAT_RED_LEVEL_REQ = "STAT_RED_LEVEL_REQ";
    public static final String STAT_CUNNING = "STAT_CUNNING";
    public static final String STAT_PHYSIQUE = "STAT_PHYSIQUE";
    public static final String STAT_SPIRIT = "STAT_SPIRIT";
    public static final String STAT_OFF_ABIL_SHORT = "STAT_OFF_ABIL_SHORT";
    public static final String STAT_DEF_ABIL_SHORT = "STAT_DEF_ABIL_SHORT";
    public static final String STAT_SKILL_HEALTH = "STAT_SKILL_HEALTH";
    public static final String STAT_HEAL_INC = "STAT_HEAL_INC";
    public static final String STAT_REGEN_HEALTH = "STAT_REGEN_HEALTH";
    public static final String STAT_HEALTH = "STAT_HEALTH";
    public static final String STAT_REGEN_ENERGY = "STAT_REGEN_ENERGY";
    public static final String STAT_ENERGY_ABSORB = "STAT_ENERGY_ABSORB";
    public static final String STAT_ENERGY = "STAT_ENERGY";
    public static final String STAT_ENERGY_LIMIT = "STAT_ENERGY_LIMIT";
    public static final String STAT_ENERGY_RESERVE = "STAT_ENERGY_RESERVE";
    public static final String STAT_SKILL_RADIUS = "STAT_SKILL_RADIUS";
    public static final String STAT_SKILL_DURATION = "STAT_SKILL_DURATION";
    public static final String STAT_PET_SUMMON = "STAT_PET_SUMMON";
    public static final String STAT_PET_LIMIT = "STAT_PET_LIMIT";
    public static final String STAT_MAX_LEVEL_INC = "STAT_MAX_LEVEL_INC";
    public static final String STAT_TARGET_INC = "STAT_TARGET_INC";
    public static final String STAT_LIGHT_RADIUS = "STAT_LIGHT_RADIUS";
    public static final String STAT_RACE_DAMAGE = "TXT_UNI_RACE_DAMAGE";
    public static final String STAT_CONSTITUTION = "STAT_CONSTITUTION";
    public static final String STAT_AVOID_PROJECTILE = "STAT_AVOID_PROJECTILE";
    public static final String STAT_AVOID_MELEE = "STAT_AVOID_MELEE";
    public static final String STAT_RED_ARMOR_STR = "STAT_RED_ARMOR_STR";
    public static final String STAT_RED_RANGED_DEX = "STAT_RED_RANGED_DEX";
    public static final String STAT_RED_MELEE_DEX = "STAT_RED_MELEE_DEX";
    public static final String STAT_RED_MELEE_STR = "STAT_RED_MELEE_STR";
    public static final String STAT_RED_WEAPON_INT = "STAT_RED_WEAPON_INT";
    public static final String STAT_RED_WEAPON_STR = "STAT_RED_WEAPON_STR";
    public static final String STAT_RED_JEWELRY_INT = "STAT_RED_JEWELRY_INT";
    public static final String STAT_RED_SHIELD_STR = "STAT_RED_SHIELD_STR";
    public static final String STAT_WEAPON_PROJECTILE_PIERCE = "STAT_PROJECTILE_PIERCE";
    public static final int DMG_CLASS_DEFENSE = 1;
    public static final int DMG_CLASS_OFFENSE = 2;
    public static final int DMG_CLASS_RETALIATION = 3;
    public static final int STAT_PHYSIQUE_FLAT = 101;
    public static final int STAT_CUNNING_FLAT = 102;
    public static final int STAT_SPIRIT_FLAT = 103;
    public static final int STAT_DEF_ABIL_FLAT = 104;
    public static final int STAT_OFF_ABIL_FLAT = 105;
    public static final int STAT_HEALTH_FLAT = 106;
    public static final int STAT_HEALTH_REGEN_FLAT = 107;
    public static final int STAT_ENERGY_REGEN_FLAT = 108;
    public static final int STAT_PHYSIQUE_PERC = 201;
    public static final int STAT_CUNNING_PERC = 202;
    public static final int STAT_SPIRIT_PERC = 203;
    public static final int STAT_DEF_ABIL_PERC = 204;
    public static final int STAT_OFF_ABIL_PERC = 205;
    public static final int STAT_HEALTH_PERC = 206;
    public static final int STAT_HEALTH_REGEN_PERC = 207;
    public static final int STAT_ENERGY_REGEN_PERC = 208;
    public static final int STAT_BONUS_XP_PERC = 209;
    public static final int STAT_ATTACK_SPEED_PERC = 210;
    public static final int STAT_CAST_SPEED_PERC = 211;
    public static final int STAT_RUN_SPEED_PERC = 212;
    public static final int STAT_TOTAL_SPEED_PERC = 213;
    public static final int STAT_COOLDOWN_RED_PERC = 214;
    public static final int STAT_SHIELD_RECOVERY_RED_PERC = 215;
    public static final int STAT_CHANCE_AVOID_MELEE_PERC = 216;
    public static final int STAT_CHANCE_AVOID_PROJECTILE_PERC = 217;
    public static final int DMG_TYPE_FLAT_POISON = 301;
    public static final int DMG_TYPE_FLAT_AETHER = 302;
    public static final int DMG_TYPE_FLAT_CHAOS = 303;
    public static final int DMG_TYPE_FLAT_COLD = 304;
    public static final int DMG_TYPE_FLAT_ELEMENTAL = 305;
    public static final int DMG_TYPE_FLAT_FIRE = 306;
    public static final int DMG_TYPE_FLAT_LIFE = 307;
    public static final int DMG_TYPE_FLAT_LIGHTNING = 308;
    public static final int DMG_TYPE_FLAT_PHYSICAL = 309;
    public static final int DMG_TYPE_FLAT_PIERCE = 310;
    public static final int DMG_TYPE_DOT_POISON = 401;
    public static final int DMG_TYPE_DOT_COLD = 404;
    public static final int DMG_TYPE_DOT_FIRE = 406;
    public static final int DMG_TYPE_DOT_LIFE = 407;
    public static final int DMG_TYPE_DOT_LIGHTNING = 408;
    public static final int DMG_TYPE_DOT_PHYSICAL = 409;
    public static final int DMG_TYPE_DOT_PIERCE = 410;
    public static final int DMG_TYPE_SPEC_TOTAL = 501;
    public static final int DMG_TYPE_SPEC_CRITICAL = 502;
    public static final int DMG_TYPE_SPEC_LIFELEECH = 503;
    public static final int DMG_TYPE_SPEC_REFLECTION = 504;
    public static final int DMG_TYPE_SPEC_SLOW_ATTACK = 505;
    public static final int DMG_TYPE_SPEC_SLOW_TOTAL = 506;
    public static final int DMG_TYPE_SPEC_SLOW_DA = 507;
    public static final int DMG_TYPE_SPEC_SLOW_OA = 508;
    public static final int DMG_TYPE_SPEC_PROJECTILE_PIERCE = 509;
    public static final int DMG_TYPE_RES_RED_ABS_TOTAL = 510;
    public static final int DMG_TYPE_RES_RED_PERC_TOTAL = 511;
    public static final int DMG_TYPE_RES_RED_ABS_PHYSICAL = 512;
    public static final int DMG_TYPE_RES_RED_PERC_PHYSICAL = 513;
    public static final int DMG_TYPE_RES_RED_ABS_ELEMENTAL = 514;
    public static final int DMG_TYPE_RES_RED_PERC_ELEMENTAL = 515;
    public static final int DMG_TYPE_SPEC_RETAL_REFLECT = 516;
    public static final int DMG_TYPE_SPEC_MANA_COST = 517;
    public static final int DMG_TYPE_RESIST_STUN = 601;
    public static final int DMG_TYPE_RESIST_SLOW = 602;
    public static final int DMG_TYPE_RESIST_TRAP = 603;
    public static final int DMG_TYPE_RESIST_PETRIFY = 604;
    public static final int DMG_TYPE_RESIST_FREEZE = 605;
    private String itemID;
    private String type;
    private int skillLevel;
    private boolean global;
    private boolean xor;
    private float statMin;
    private float statMax;
    private int statChance;
    private int statModifier;
    private int statModifierChance;
    private int durationMin;
    private int durationMax;
    private int durationChance;
    private int durationModifier;
    private int durationModifierChance;
    private int maxResist;
    private DBItem itemGlobal;
    private DBAffix affixGlobal;
    private int globalType;
    private boolean petStat;
    private DBStatBonusRace statBonusRace;

    public DBStat() {
        this.itemID = null;
        this.type = null;
        this.skillLevel = 0;
        this.global = false;
        this.xor = false;
        this.statMin = 0.0f;
        this.statMax = 0.0f;
        this.statChance = 0;
        this.statModifier = 0;
        this.statModifierChance = 0;
        this.durationMin = 0;
        this.durationMax = 0;
        this.durationChance = 0;
        this.durationModifier = 0;
        this.durationModifierChance = 0;
        this.maxResist = 0;
        this.itemGlobal = null;
        this.affixGlobal = null;
        this.globalType = 0;
        this.petStat = false;
        this.statBonusRace = null;
    }

    public DBStat(final DBStat stat, final DBStatBonusRace statBonusRace) {
        this.fillFromStat(stat);
        this.statBonusRace = statBonusRace;
    }

    private DBStat(final DBStat stat) {
        this.fillFromStat(stat);
    }

    public DBStat clone() {
        return new DBStat(this);
    }

    public boolean isInitial() {
        return !this.global && !this.xor && this.statMin == 0.0f && this.statMax == 0.0f && this.statChance == 0 && this.statModifier == 0 && this.statModifierChance == 0 && this.durationMin == 0 && this.durationMax == 0 && this.durationChance == 0 && this.durationModifier == 0 && this.durationModifierChance == 0 && this.maxResist == 0;
    }

    public void fillFromStat(final DBStat stat) {
        this.itemID = stat.itemID;
        this.type = stat.type;
        this.skillLevel = stat.skillLevel;
        this.global = stat.global;
        this.xor = stat.xor;
        this.statMin = stat.statMin;
        this.statMax = stat.statMax;
        this.statChance = stat.statChance;
        this.statModifier = stat.statModifier;
        this.statModifierChance = stat.statModifierChance;
        this.durationMin = stat.durationMin;
        this.durationMax = stat.durationMax;
        this.durationChance = stat.durationChance;
        this.durationModifier = stat.durationModifier;
        this.durationModifierChance = stat.durationModifierChance;
        this.maxResist = stat.maxResist;
        this.itemGlobal = stat.itemGlobal;
        this.affixGlobal = stat.affixGlobal;
        this.globalType = stat.globalType;
        this.petStat = stat.petStat;
        if (stat.statBonusRace != null) {
            this.statBonusRace = stat.statBonusRace.clone();
        }
    }

    public static List<DBStat> createStatsFromRaceBonusList(final DBStat base, final List<DBStatBonusRace> list) {
        final List<DBStat> stats = new LinkedList<DBStat>();
        if (list == null) {
            stats.add(base);
            return stats;
        }
        if (list.isEmpty()) {
            stats.add(base);
            return stats;
        }
        for (DBStatBonusRace br : list) {
            br = br.clone();
            final DBStat stat = new DBStat(base, br);
            stats.add(stat);
        }
        return stats;
    }

    @Override
    public boolean equals(final Object o) {
        if (o == null) {
            return false;
        }
        if (!o.getClass().equals(DBStat.class)) {
            return false;
        }
        final DBStat stat = (DBStat) o;
        return this.itemID.equals(stat.itemID) && this.type.equals(stat.type) && (this.statBonusRace != null || stat.statBonusRace == null) && (this.statBonusRace == null || stat.statBonusRace != null) && (this.statBonusRace == null || this.statBonusRace.equals(stat.statBonusRace)) && this.skillLevel == stat.skillLevel;
    }

    @Override
    public int hashCode() {
        return this.itemID.hashCode() + this.type.hashCode() + this.skillLevel;
    }

    @Override
    public int compareTo(final DBStat o) {
        if (!o.getClass().equals(DBStat.class)) {
            final Object[] args = {DBStat.class, o.toString()};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_NOT_OF_TYPE", args);
            throw new ClassCastException(msg);
        }
        final DBStat stat = o;
        int comp = 0;
        comp = this.itemID.compareTo(stat.itemID);
        if (comp != 0) {
            return comp;
        }
        comp = this.type.compareTo(stat.type);
        if (comp != 0) {
            return comp;
        }
        return this.skillLevel - stat.skillLevel;
    }

    public String getItemID() {
        return this.itemID;
    }

    public void setItemID(final String itemID) {
        this.itemID = itemID;
    }

    public String getStatType() {
        return this.type;
    }

    public void setStatType(final String type) {
        this.type = type;
    }

    public boolean isPetStat() {
        return this.petStat;
    }

    public void setPetStat(final boolean petStat) {
        this.petStat = petStat;
    }

    public int getSkillLevel() {
        return this.skillLevel;
    }

    public void setSkillLevel(final int skillLevel) {
        this.skillLevel = skillLevel;
    }

    public boolean isGlobal() {
        return this.global;
    }

    public void setGlobal(final boolean global) {
        this.global = global;
    }

    public boolean isXOR() {
        return this.xor;
    }

    public void setXOR(final boolean xor) {
        this.xor = xor;
    }

    public float getStatMin() {
        return this.statMin;
    }

    public void setStatMin(final float statMin) {
        this.statMin = statMin;
    }

    public float getStatMax() {
        return this.statMax;
    }

    public void setStatMax(final float statMax) {
        this.statMax = statMax;
    }

    public int getStatChance() {
        return this.statChance;
    }

    public void setStatChance(final int statChance) {
        this.statChance = statChance;
    }

    public int getStatModifier() {
        return this.statModifier;
    }

    public void setStatModifier(final int statModifier) {
        this.statModifier = statModifier;
    }

    public int getStatModifierChance() {
        return this.statModifierChance;
    }

    public static DBStat getDBStat(final List<DBStat> dbStats, final String search, final int level) {
        DBStat bestFit = null;
        for (final DBStat dbStat : dbStats) {
            if (dbStat == null) {
                continue;
            }
            if (!dbStat.getStatType().equals(search)) {
                continue;
            }
            if (dbStat.getSkillLevel() > level) {
                continue;
            }
            if (bestFit == null) {
                bestFit = dbStat;
            } else if (bestFit.getSkillLevel() < dbStat.getSkillLevel()) {
                bestFit = dbStat;
            }
            if (dbStat.getSkillLevel() == level) {
                break;
            }
        }
        return bestFit;
    }

    public static List<DBStat> getStatsForExactLevel(final List<DBStat> dbStats, final int level) {
        final List<DBStat> list = new LinkedList<DBStat>();
        for (final DBStat dbStat : dbStats) {
            if (dbStat == null) {
                continue;
            }
            if (dbStat.getSkillLevel() != level) {
                continue;
            }
            list.add(dbStat);
        }
        return list;
    }

    public static List<DBStat> getStatsForLevel(final List<DBStat> dbStats, final int level) {
        final List<DBStat> list = new LinkedList<DBStat>();
        for (final DBStat dbStat : dbStats) {
            if (dbStat == null) {
                continue;
            }
            if (dbStat.getSkillLevel() > level) {
                continue;
            }
            boolean found = false;
            final Iterator<DBStat> iter = list.iterator();
            while (iter.hasNext()) {
                final DBStat dbs = iter.next();
                if (!dbs.itemID.equals(dbStat.itemID)) {
                    continue;
                }
                if (!dbs.type.equals(dbStat.type)) {
                    continue;
                }
                found = true;
                if (dbs.skillLevel < dbStat.skillLevel) {
                    iter.remove();
                    found = false;
                    break;
                }
                break;
            }
            if (found) {
                continue;
            }
            list.add(dbStat);
        }
        return list;
    }

    public void setStatModifierChance(final int statModifierChance) {
        this.statModifierChance = statModifierChance;
    }

    public int getMinDuration() {
        return this.durationMin;
    }

    public void setMinDuration(final int durationMin) {
        this.durationMin = durationMin;
    }

    public int getMaxDuration() {
        return this.durationMax;
    }

    public void setMaxDuration(final int durationMax) {
        this.durationMax = durationMax;
    }

    public int getDurationChance() {
        return this.durationChance;
    }

    public void setDurationChance(final int durationChance) {
        this.durationChance = durationChance;
    }

    public int getDurationModifier() {
        return this.durationModifier;
    }

    public void setDurationModifier(final int durationModifier) {
        this.durationModifier = durationModifier;
    }

    public int getDurationModifierChance() {
        return this.durationModifierChance;
    }

    public void setDurationModifierChance(final int durationModifierChance) {
        this.durationModifierChance = durationModifierChance;
    }

    public int getMaxResist() {
        return this.maxResist;
    }

    public void setMaxResist(final int maxResist) {
        this.maxResist = maxResist;
    }

    public int getGlobalOffensePerc() {
        if (this.itemGlobal != null) {
            return this.itemGlobal.getOffensiveChance();
        }
        if (this.affixGlobal != null) {
            return this.affixGlobal.getOffensiveChance();
        }
        return -1;
    }

    public int getGlobalRetaliationPerc() {
        if (this.itemGlobal != null) {
            return this.itemGlobal.getRetaliationChance();
        }
        if (this.affixGlobal != null) {
            return this.affixGlobal.getRetaliationChance();
        }
        return -1;
    }

    public int getGlobalCategory() {
        return this.globalType;
    }

    public DBStatBonusRace getBonusRace() {
        return this.statBonusRace;
    }

    public void setBonusRace(final DBStatBonusRace statBonusRace) {
        this.statBonusRace = statBonusRace;
    }

    public static void createItemTable(final Connection conn) throws SQLException {
        createTable(conn, "GD_ITEM_STAT", "ITEM_ID");
    }

    public static void createItemSetTable(final Connection conn) throws SQLException {
        createTable(conn, "GD_ITEMSET_STAT", "ITEMSET_ID");
    }

    public static void createAffixTable(final Connection conn) throws SQLException {
        createTable(conn, "GD_AFFIX_STAT", "AFFIX_ID");
    }

    public static void createSkillTable(final Connection conn) throws SQLException {
        createTable(conn, "GD_SKILL_STAT", "SKILL_ID");
    }

    private static void createTable(final Connection conn, final String tabName, final String idName) throws SQLException {
        final String dropTable = "DROP TABLE " + tabName;
        final String createTable = "CREATE TABLE " + tabName + " (" + idName + "                VARCHAR(" + "256" + ") NOT NULL, STAT_TYPE                VARCHAR(" + "64" + ") NOT NULL, SKILL_LEVEL              INTEGER, FLAG_GLOBAL              BOOLEAN, FLAG_XOR                 BOOLEAN, STAT_MIN                 FLOAT,   STAT_MAX                 FLOAT,   STAT_CHANCE              INTEGER, MODIFIER                 INTEGER, MODIFIER_CHANCE          INTEGER, DURATION_MIN             INTEGER, DURATION_MAX             INTEGER, DURATION_CHANCE          INTEGER, DURATION_MODIFIER        INTEGER, DURATION_MODIFIER_CHANCE INTEGER, MAX_RESIST               INTEGER, PRIMARY KEY (" + idName + ", STAT_TYPE, SKILL_LEVEL))";
        try (final Statement st = conn.createStatement()) {
            if (GDDBUtil.tableExists(conn, tabName)) {
                st.execute(dropTable);
            }
            st.execute(createTable);
            st.close();
            conn.commit();
        } catch (SQLException ex) {
            final Object[] args = {tabName};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_CREATE_TABLE", args);
            GDMsgLogger.addError(msg);
            throw ex;
        }
    }

    public static void deleteItem(final Connection conn, final String id) throws SQLException {
        delete(conn, "GD_ITEM_STAT", "ITEM_ID", id);
    }

    public static void deleteItemSet(final Connection conn, final String id) throws SQLException {
        delete(conn, "GD_ITEMSET_STAT", "ITEMSET_ID", id);
    }

    public static void deleteAffix(final Connection conn, final String id) throws SQLException {
        delete(conn, "GD_AFFIX_STAT", "AFFIX_ID", id);
    }

    public static void deleteSkill(final Connection conn, final String id) throws SQLException {
        delete(conn, "GD_SKILL_STAT", "SKILL_ID", id);
    }

    private static void delete(final Connection conn, final String tabName, final String idName, final String id) throws SQLException {
        final String deleteEntry = "DELETE FROM " + tabName + " WHERE " + idName + " = ?";
        try (final PreparedStatement ps = conn.prepareStatement(deleteEntry)) {
            ps.setString(1, id);
            ps.executeUpdate();
            ps.close();
        } catch (SQLException ex) {
            throw ex;
        }
    }

    public static void insertItem(final Connection conn, final String id, final List<DBStat> stats) throws SQLException {
        insert(conn, "GD_ITEM_STAT", id, stats);
    }

    public static void insertItemSet(final Connection conn, final String id, final List<DBStat> stats) throws SQLException {
        insert(conn, "GD_ITEMSET_STAT", id, stats);
    }

    public static void insertAffix(final Connection conn, final String id, final List<DBStat> stats) throws SQLException {
        insert(conn, "GD_AFFIX_STAT", id, stats);
    }

    public static void insertSkill(final Connection conn, final String id, final List<DBStat> stats) throws SQLException {
        insert(conn, "GD_SKILL_STAT", id, stats);
    }

    private static void insert(final Connection conn, final String tabName, final String id, final List<DBStat> stats) throws SQLException {
        final String insert = "INSERT INTO " + tabName + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        if (stats == null) {
            return;
        }
        if (stats.isEmpty()) {
            return;
        }
        try (final PreparedStatement ps = conn.prepareStatement(insert)) {
            for (final DBStat stat : stats) {
                if (!stat.isInitial()) {
                    ps.setString(1, id);
                    ps.setString(2, stat.type);
                    ps.setInt(3, stat.skillLevel);
                    ps.setBoolean(4, stat.global);
                    ps.setBoolean(5, stat.xor);
                    ps.setFloat(6, stat.statMin);
                    ps.setFloat(7, stat.statMax);
                    ps.setInt(8, stat.statChance);
                    ps.setInt(9, stat.statModifier);
                    ps.setInt(10, stat.statModifierChance);
                    ps.setInt(11, stat.durationMin);
                    ps.setInt(12, stat.durationMax);
                    ps.setInt(13, stat.durationChance);
                    ps.setInt(14, stat.durationModifier);
                    ps.setInt(15, stat.durationModifierChance);
                    ps.setInt(16, stat.maxResist);
                    ps.executeUpdate();
                    ps.clearParameters();
                }
            }
            ps.close();
        }
    }

    public static List<DBStat> getItem(final String id) throws SQLException {
        return get("GD_ITEM_STAT", "ITEM_ID", id);
    }

    public static List<DBStat> getItemSet(final String id) throws SQLException {
        return get("GD_ITEMSET_STAT", "ITEMSET_ID", id);
    }

    public static List<DBStat> getAffix(final String id) throws SQLException {
        return get("GD_AFFIX_STAT", "AFFIX_ID", id);
    }

    public static List<DBStat> getSkill(final String id) throws SQLException {
        return get("GD_SKILL_STAT", "SKILL_ID", id);
    }

    private static List<DBStat> get(final String tabName, final String idName, final String id) {
        List<DBStat> list = new LinkedList<DBStat>();
        final String command = "SELECT * FROM " + tabName + " WHERE " + idName + " = ?";
        try (final Connection conn = GDDBData.getConnection();
             final PreparedStatement ps = conn.prepareStatement(command)) {
            ps.setString(1, id);
            try (final ResultSet rs = ps.executeQuery()) {
                list = wrap(rs);
                conn.commit();
            } catch (SQLException ex) {
                throw ex;
            }
        } catch (SQLException ex2) {
            final Object[] args = {id, tabName};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_READ_TABLE_BY_ID", args);
            GDMsgLogger.addError(msg);
            GDMsgLogger.addError(ex2);
        }
        return list;
    }

    private static List<DBStat> wrap(final ResultSet rs) throws SQLException {
        final LinkedList<DBStat> list = new LinkedList<DBStat>();
        while (rs.next()) {
            final DBStat stat = new DBStat();
            stat.itemID = rs.getString(1);
            stat.type = rs.getString(2);
            stat.skillLevel = rs.getInt(3);
            stat.global = rs.getBoolean(4);
            stat.xor = rs.getBoolean(5);
            stat.statMin = rs.getFloat(6);
            stat.statMax = rs.getFloat(7);
            stat.statChance = rs.getInt(8);
            stat.statModifier = rs.getInt(9);
            stat.statModifierChance = rs.getInt(10);
            stat.durationMin = rs.getInt(11);
            stat.durationMax = rs.getInt(12);
            stat.durationChance = rs.getInt(13);
            stat.durationModifier = rs.getInt(14);
            stat.durationModifierChance = rs.getInt(15);
            stat.maxResist = rs.getInt(16);
            list.add(stat);
        }
        return list;
    }

    public static DBStat getByType(final List<DBStat> stats, final String statType, final int level) {
        DBStat stat = null;
        int maxLevel = -1;
        if (stats == null) {
            return null;
        }
        for (final DBStat temp : stats) {
            if (temp.getStatType().equals(statType)) {
                if (temp.skillLevel <= level && temp.skillLevel > maxLevel) {
                    stat = temp;
                    maxLevel = temp.skillLevel;
                }
                if (temp.skillLevel == level) {
                    break;
                }
                continue;
            }
        }
        return stat;
    }

    public static List<DBStat> getByLevel(final List<DBStat> stats, final int level) {
        final List<DBStat> list = new LinkedList<DBStat>();
        if (stats == null) {
            return list;
        }
        for (final DBStat stat : stats) {
            if (stat.skillLevel > level) {
                continue;
            }
            boolean found = false;
            for (final DBStat temp : list) {
                if (temp.type.equals(stat.type) && temp.isPetStat() == stat.isPetStat()) {
                    found = true;
                    if (temp.skillLevel < stat.skillLevel) {
                        temp.fillFromStat(stat);
                        break;
                    }
                    break;
                }
            }
            if (found) {
                continue;
            }
            list.add(stat.clone());
        }
        return list;
    }

    public static void applyAttributeScale(final List<DBStat> stats, final int scale) {
        if (stats == null) {
            return;
        }
        if (scale == 0) {
            return;
        }
        final float factor = (100 + scale) / 100.0f;
        for (final DBStat stat : stats) {
            final TagInfo info = TagInfoHashMap.getInfo(stat.getStatType());
            if (info == null) {
                continue;
            }
            if (!info.isScaling()) {
                continue;
            }
            stat.statMin = (float) (int) (stat.statMin * factor);
            stat.statMax = (float) (int) (stat.statMax * factor);
            stat.statModifier *= (int) factor;
        }
    }

    public static boolean statsMeetCriteria(final List<DBStat> stats, final SelectionCriteria criteria) {
        if (criteria.combiMode == SelectionCriteria.CombinationMode.OR) {
            return true;
        }
        boolean fitsAll = true;
        for (final SelectionCriteria.StatInfo statInfo : criteria.statInfos) {
            boolean found = false;
            if (statInfo.combo == SelectionCriteria.ComboType.OR) {
                continue;
            }
            for (final String statType : statInfo.statTypes) {
                for (final DBStat stat : stats) {
                    if (stat.getStatType().equals(statType)) {
                        if (statInfo.flat && stat.getStatMin() > 0.0f) {
                            found = true;
                            break;
                        }
                        if (statInfo.percentage && stat.getStatModifier() > 0) {
                            found = true;
                            break;
                        }
                        if (statInfo.maxResist && stat.getMaxResist() > 0) {
                            found = true;
                            break;
                        }
                        continue;
                    }
                }
                if (found) {
                    break;
                }
            }
            if (!found) {
                fitsAll = false;
                break;
            }
        }
        return fitsAll;
    }

    public static void add(final List<DBStat> list, final DBItem item, final int globalType, final List<DBStat> addList) {
        add(list, item, null, globalType, addList);
    }

    public static void add(final List<DBStat> list, final DBAffix affix, final int globalType, final List<DBStat> addList) {
        add(list, null, affix, globalType, addList);
    }

    private static void add(final List<DBStat> list, final DBItem item, final DBAffix affix, final int globalType, final List<DBStat> addList) {
        if (addList == null) {
            return;
        }
        for (DBStat statAdd : addList) {
            statAdd = statAdd.clone();
            if (statAdd.global) {
                if (item != null) {
                    statAdd.itemGlobal = item;
                }
                if (affix != null) {
                    statAdd.affixGlobal = affix;
                }
                statAdd.globalType = globalType;
                list.add(statAdd);
            } else {
                for (final DBStat stat : list) {
                    if (stat.global) {
                        continue;
                    }
                    boolean found = false;
                    if (!statAdd.type.equals(stat.type)) {
                        continue;
                    }
                    if (!found && stat.type.equals("racialBonusPercentDamage")) {
                        if (stat.statBonusRace == null) {
                            continue;
                        }
                        if (!stat.statBonusRace.equals(statAdd.statBonusRace)) {
                            continue;
                        }
                        if (statAdd.statMin > 0.0f) {
                            stat.statMin += statAdd.statMin;
                        }
                        statAdd.statMin = 0.0f;
                        found = true;
                    }
                    if (found) {
                        continue;
                    }
                    if (statAdd.statMin > 0.0f) {
                        if (stat.statMin == 0.0f) {
                            stat.statMin = statAdd.statMin;
                            stat.statMax = statAdd.statMax;
                            stat.statChance = statAdd.statChance;
                            stat.durationMin = statAdd.durationMin;
                            statAdd.statMin = 0.0f;
                            statAdd.statMax = 0.0f;
                            statAdd.statChance = 0;
                            statAdd.durationMin = 0;
                        } else {
                            boolean match = true;
                            if (statAdd.durationMin != stat.durationMin) {
                                match = false;
                            }
                            if (statAdd.statChance != stat.statChance) {
                                match = false;
                            }
                            if (match) {
                                stat.statMin += statAdd.statMin;
                                if (stat.statMax > 0.0f) {
                                    if (statAdd.statMax > 0.0f) {
                                        stat.statMax += statAdd.statMax;
                                    } else {
                                        stat.statMax += statAdd.statMin;
                                    }
                                } else if (statAdd.statMax > 0.0f) {
                                    stat.statMax = stat.statMin + statAdd.statMax;
                                }
                                statAdd.statMin = 0.0f;
                                statAdd.statMax = 0.0f;
                                statAdd.statChance = 0;
                                statAdd.durationMin = 0;
                            }
                        }
                    }
                    if (statAdd.statModifier > 0) {
                        if (stat.statModifier == 0) {
                            stat.statModifier = statAdd.statModifier;
                            stat.statModifierChance = statAdd.statModifierChance;
                            statAdd.statModifier = 0;
                            statAdd.statModifierChance = 0;
                        } else {
                            boolean match = true;
                            if (statAdd.statModifierChance != stat.statModifierChance) {
                                match = false;
                            }
                            if (match) {
                                stat.statModifier += statAdd.statModifier;
                                statAdd.statModifier = 0;
                                statAdd.statModifierChance = 0;
                            }
                        }
                    }
                    if (statAdd.maxResist <= 0) {
                        continue;
                    }
                    stat.maxResist += statAdd.maxResist;
                    statAdd.maxResist = 0;
                }
                if (statAdd.isInitial() || statAdd.global) {
                    continue;
                }
                list.add(statAdd);
            }
        }
    }

    public BonusDetail getBonusDetail(final DBStashItem item, final int detailType, final String prefix) {
        BonusDetail bonus = null;
        if (this.type == null) {
            return bonus;
        }
        bonus = new BonusDetail(item, detailType, this, prefix);
        return bonus;
    }
}
